#include <malloc.h>
#include <android_utility.h>
#include "gles_utility.h"

GLuint glesLoadShader(GLenum type, const char *shaderSrc) {
    GLuint shader;
    GLint compiled;
    shader = glCreateShader(type);
    if (shader == GL_NONE) {
        LOGE("create shader failure!");
        return GL_FALSE;
    }
    glShaderSource(shader, 1, &shaderSrc, nullptr);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (compiled) return shader;
    GLint len;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
    if (len > 1) {
        char *info = static_cast<char *>(malloc(sizeof(char) * len));
        glGetShaderInfoLog(shader, len, nullptr, info);
        LOGE("Error compiling shader -> %s", info);
        free(info);
    }
    glDeleteShader(shader);
    return GL_FALSE;
}

GLuint glesInitialize(const char *vShaderSrc, const char *fShaderSrc) {
    GLuint vertexShader = glesLoadShader(GL_VERTEX_SHADER, vShaderSrc);
    GLuint fragmentShader = glesLoadShader(GL_FRAGMENT_SHADER, fShaderSrc);
    GLuint programObject = glCreateProgram();
    if (programObject == GL_NONE) {
        LOGE("create program failure!");
        return GL_FALSE;
    }
    GLint linked;
    glAttachShader(programObject, vertexShader);
    glAttachShader(programObject, fragmentShader);
    glLinkProgram(programObject);
    glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
    if (linked)return programObject;
    GLint len = 0;
    glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &len);
    if (len > 1) {
        char *info = static_cast<char *>(malloc(sizeof(char) * len));
        glGetProgramInfoLog(programObject, len, nullptr, info);
        LOGE("Error linking program -> %s", info);
        free(info);
    }
    glDeleteProgram(programObject);
    return GL_FALSE;
}

void glesLogIntegerv(GLuint program, const char *attrName) {
    GLint maxDrawBuffers;
    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); // location中的值为[0,maxDrawBuffers-1]
    LOGI("max draw buffers -> %d", maxDrawBuffers);
    GLint maxVertexAttrs;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttrs);
    LOGI("max vertex attributes -> %d", maxVertexAttrs);
    GLint maxVertexOutCom;
    glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutCom);
    LOGI("max vertex output components -> %d", maxVertexOutCom);
    GLint maxFragInCom;
    glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &maxFragInCom);
    LOGI("max fragment input components -> %d", maxFragInCom);
    GLint maxVertexUniVec;
    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniVec);
    LOGI("max vertex uniform vectors -> %d", maxVertexUniVec);
    GLint maxFragUniVec;
    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragUniVec);
    LOGI("max fragment uniform vectors -> %d", maxFragUniVec);
    GLint actAttrsNum;
    glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &actAttrsNum); // 获取活动顶点属性数量
    LOGI("active attributes count -> %d", actAttrsNum);
    for (int i = 0; i < actAttrsNum; ++i) {
        const uint LEN = 12;
        char *attr = static_cast<char *>(malloc(sizeof(char) * LEN));
        GLint size;
        GLenum type;
        glGetActiveAttrib(program, static_cast<GLuint>(i), LEN, nullptr, &size, &type, attr);
        LOGI("attr index %d -> size:%d, type:%d, attr:%s", i, size, type, attr);
        free(attr);
    }
    if (attrName) {
        LOGI("attribute %s location -> %d", attrName, glGetAttribLocation(program, attrName));
    }
}